package com.ytt.core.service.service.teacher;


import com.ytt.core.model.common.PageDataDTO;
import com.ytt.core.model.common.SimpleDataDTO;
import com.ytt.core.model.teacher.TeacherDto;
import com.ytt.core.model.teacher.TeacherEditDto;
import com.ytt.core.model.user.UserDto;
import com.ytt.core.service.entity.role.Role;
import com.ytt.core.service.entity.teacher.Teacher;
import com.ytt.core.service.entity.user.User;
import com.ytt.core.service.exception.NoSuchDataException;
import com.ytt.core.service.mapper.teacher.TeacherMapper;
import com.ytt.core.service.mapper.user.UserMapper;
import com.ytt.core.service.repository.RoleRepository;
import com.ytt.core.service.repository.TeacherRepository;
import com.ytt.core.service.repository.UserRepository;
import com.ytt.core.service.service.ProposalQueryParam;
import com.ytt.core.service.utils.BaseUtil;
import com.ytt.core.service.utils.PageDataUtil;
import com.ytt.core.util.jpa.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service("teacherService")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class TeacherImpl implements  TeacherService {
    private static final String PASS_PLACE_HOLDER = "$pWd$(C%#*(78))!<>";
    private  final TeacherRepository teacherRepository;
    
    private  final TeacherMapper teacherMapper;

    private  final UserMapper userMapper;

    private  final UserRepository userRepository;

    private  final RoleRepository roleRepository;

    @Autowired
    public TeacherImpl(TeacherRepository teacherRepository, TeacherMapper teacherMapper, UserMapper userMapper, UserRepository userRepository, RoleRepository roleRepository) {
        this.teacherRepository = teacherRepository;
        this.teacherMapper = teacherMapper;
        this.userMapper = userMapper;
        this.userRepository = userRepository;
        this.roleRepository = roleRepository;
    }

    @Override
    public TeacherDto findById(String id) {
        return null;
    }

    @Override
    public List<TeacherDto> findAll(String sort, ProposalQueryParam param){
    List<Sort.Order> orders = PageHelper.toSortOrderList(sort);
    Sort sort1 = Sort.by(orders);
    List<Teacher> notifications = this.teacherRepository.findAll(
            BaseUtil.<Teacher>getBuilder(param).build(),sort1);
        return notifications.stream().map(this.teacherMapper::toDTO).collect(Collectors.toList()).stream().peek(n->{
        UserDto userDto=n.getUser();
        //设置用户的密码 防止密码返回真实的数据泄露
        userDto.setPassword(PASS_PLACE_HOLDER);
        n.setUser(userDto);
    }).collect(Collectors.toList());
    }

    @Override
    public PageDataDTO<TeacherDto> findOnePage(Integer page, Integer size, String sort, ProposalQueryParam param) {
        Page<Teacher> notificationPage = this.teacherRepository.findAll(
                BaseUtil.<Teacher>getBuilder(param).build(), PageHelper.generatePageRequest(page, size, sort));
        List<TeacherDto> notificationDTOList = notificationPage.getContent().stream().map(this.teacherMapper::toDTO)
                .collect(Collectors.toList()).stream().peek(n->{
                    UserDto userDto=n.getUser();
                    //设置用户的密码 防止密码返回真实的数据泄露
                    userDto.setPassword(PASS_PLACE_HOLDER);
                    n.setUser(userDto);
                }).collect(Collectors.toList());
        return PageDataUtil.toPageData(notificationPage, notificationDTOList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TeacherDto create(TeacherEditDto saveDTO){
    User user=new User();
        userMapper.updateEntity(saveDTO,user);
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
    //设置教师的角色
    Optional<Role> role= roleRepository.findById(2L);
        if(role.isPresent()) {
        Set<Role> roles=new HashSet<>();
        roles.add(role.get());
        user.setRoles(roles);
    }
    user = this.userRepository.save(user);


    Teacher entity = new Teacher();
        this.teacherMapper.updateEntity(saveDTO, entity);
        entity.setUser(user);
    entity = this.teacherRepository.save(entity);

    TeacherDto teacherDto=  this.teacherMapper.toDTO(entity);
    UserDto userDto=this.userMapper.toDTO(user);
    //设置用户的密码 防止密码返回真实的数据泄露
        userDto.setPassword(PASS_PLACE_HOLDER);
        teacherDto.setUser(userDto);
        return teacherDto;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TeacherDto update(String id, TeacherEditDto saveDTO) {

        Optional<Teacher> optional = this.teacherRepository.findById(Long.valueOf(id));
        Teacher entity = optional.orElseThrow(() -> new NoSuchDataException(id));

        this.teacherMapper.updateEntity(saveDTO, entity);
        entity = this.teacherRepository.saveAndFlush(entity);

        Optional<User> optionalUser = this.userRepository.findById(entity.getUser().getId());
        User user = optionalUser.orElseThrow(() -> new NoSuchDataException(id));
        saveDTO.setId(String.valueOf(entity.getUser().getId()));
        userMapper.updateEntity(saveDTO,user);
        String oldPwd = optionalUser.get().getPassword();
        if (!PASS_PLACE_HOLDER.equals(saveDTO.getPassword())) {
            user.setPassword(new BCryptPasswordEncoder().encode(saveDTO.getPassword()));
        } else {
            user.setPassword(oldPwd);
        }
        user = this.userRepository.saveAndFlush(user);

        TeacherDto teacherDto=  this.teacherMapper.toDTO(entity);
        UserDto userDto=this.userMapper.toDTO(user);
        //设置用户的密码 防止密码返回真实的数据泄露
        userDto.setPassword(PASS_PLACE_HOLDER);
        teacherDto.setUser(userDto);
        return teacherDto;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(String id) {
        Teacher entity = this.teacherRepository.findById(Long.valueOf(id)).orElseThrow(() -> new NoSuchDataException(id));
        this.teacherRepository.delete(entity);

        User user = this.userRepository.findById(entity.getUser().getId()).orElseThrow(() -> new NoSuchDataException(String.valueOf(entity.getUser().getId())));
        //解锁用户角色
        user.getRoles().forEach(role -> role.getUsers().remove(user));
        this.userRepository.delete(user);
    }

    @Override
    public SimpleDataDTO<Boolean> checkJobNumberAvailability(String id, String job_number) {
        String foundUserId = this.findByJob_number(job_number);
        if (foundUserId == null) {
            return new SimpleDataDTO<>(true);
        } else {
            boolean rtn = id != null && id.equalsIgnoreCase(foundUserId);
            return new SimpleDataDTO<>(rtn);
        }
    }

    @Override
    public String findByJob_number(String key) {
        Long id = teacherRepository.findByJob_number(key);
        if (id == null) {
            return  null;
        } else {
            return String.valueOf(id);
        }
    }
}
